package com.iscreen.dbupgrade.queries.mysql;

import java.util.ArrayList;
import java.util.List;

import com.iscreen.dbupgrade.objects.FieldType;
import com.iscreen.dbupgrade.objects.NewField;
import com.iscreen.dbupgrade.queries.QueryUtils;
import com.iscreen.dbupgrade.queries.constants.DBConstants;
import com.iscreen.dbupgrade.queries.constants.mysql.MySqlDBConstants;
import com.iscreen.utils.db.connection.DBConnection;
import com.iscreen.utils.db.query.Query;
import com.iscreen.utils.exceptions.IScreenException;
import com.iscreen.utils.strings.StringUtils;

public class MySqlQueryUtils extends QueryUtils
{

	public MySqlQueryUtils(DBConnection connection)
	{
		super(connection);
	}

	@Override
	public String getFieldTypeSql(NewField field)
	{
		FieldType type = field.getType();
		switch (type)
		{
		case BOOLEAN:
			return DBConstants.BOOLEAN;
		case DECIMAL:
			return DBConstants.DECIMAL + "(" + DBConstants.DECIMAL_DIGITS + ","
					+ DBConstants.DECIMAL_PRECISION + ")";
		case DATE:
			return DBConstants.DATE;
		case ID:
			return DBConstants.BIGINT + " " + DBConstants.UNSIGNED;
		case STRING:
			int length;
			if (field.getLength() == null || field.getLength() == 0)
			{
				length = DBConstants.STRING_DEF_LEN;
			}
			else
			{
				length = field.getLength();
			}
			return DBConstants.VARCHAR + "(" + length + ")";
		case TIMESTAMP:
			return DBConstants.TIMESTAMP;
		}
		;
		return null;
	}

	@Override
	public FieldType getFieldType(String fieldTypeSql)
	{
		String typeSql = fieldTypeSql;
		if (fieldTypeSql.indexOf('(') > 0)
		{
			typeSql = fieldTypeSql.substring(0,fieldTypeSql.indexOf('(')) + fieldTypeSql.substring(fieldTypeSql.indexOf(')')+1);
		}
		if (typeSql.equalsIgnoreCase(DBConstants.BOOLEAN))
		{
			return FieldType.BOOLEAN;
		}
		else if (typeSql.equalsIgnoreCase(DBConstants.DECIMAL))
		{
			return FieldType.DECIMAL;
		}
		else if (typeSql.equalsIgnoreCase(DBConstants.DATE))
		{
			return FieldType.DATE;
		}
		else if (typeSql.equalsIgnoreCase(DBConstants.BIGINT + " " + DBConstants.UNSIGNED))
		{
			return FieldType.ID;
		}
		else if (typeSql.equalsIgnoreCase(DBConstants.VARCHAR))
		{
			return FieldType.STRING;
		}
		else if (typeSql.equalsIgnoreCase(DBConstants.TIMESTAMP))
		{
			return FieldType.TIMESTAMP;
		}
		return null;
	}

	@Override
	public Integer getFieldLength(String fieldTypeSql)
	{
		if (fieldTypeSql.indexOf('(') > 0)
		{
			return Integer.parseInt(fieldTypeSql.substring(fieldTypeSql.indexOf('(') + 1, fieldTypeSql.indexOf(')')));
		}
		else
		{
			return null;
		}

	}
	
	private boolean isFieldMandatory(String fieldNullSql)
	{
		return !StringUtils.parseYesNoString(fieldNullSql,true);
	}

	private boolean isFieldPrimaryKey(String fieldKeySql)
	{
		return (fieldKeySql != null) && 
				(fieldKeySql.equalsIgnoreCase(MySqlDBConstants.COLUMN_PRIMARY_KEY));
	}
	
	@Override
	public List<NewField> getFields(String tableName) throws IScreenException
	{
		List<NewField> fields = new ArrayList<NewField>();
		String sql = getFieldsSql(tableName);
		Query query = connection.createQuery(sql);
		try
		{
			query.open();
			while (query.next())
			{
				NewField field = new NewField();
				field.setName(query.getString(MySqlDBConstants.COLUMN_FIELD));
				field.setType(getFieldType(query.getString(MySqlDBConstants.COLUMN_TYPE)));
				field.setLength(getFieldLength(query.getString(MySqlDBConstants.COLUMN_TYPE)));
				field.setDefault(query.getObject(MySqlDBConstants.COLUMN_DEFAULT));
				field.setMandatory(isFieldMandatory(query.getString(MySqlDBConstants.COLUMN_NULL)));
				field.setPk(isFieldPrimaryKey(query.getString(MySqlDBConstants.COLUMN_KEY)));
				fields.add(field);
			}
		}
		finally
		{
			query.close();
		}
		return fields;
	}

	private String getFieldsSql(String tableName)
	{
		StringBuilder sqlBuilder = new StringBuilder();
		sqlBuilder.append(MySqlDBConstants.SHOW_COLUMNS + " ");
		sqlBuilder.append(DBConstants.FROM + " ");
		sqlBuilder.append(tableName);
		return sqlBuilder.toString();
	}

}
